#include "StdAfx.h"
#include "HTTPMgr.h"

CHTTPMgr::CHTTPMgr( void ) :
	m_hInternetSession(	NULL ),
	m_dwLastError(		NULL )
{
	this->m_hInternetSession = ::InternetOpen( NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL );
}

CHTTPMgr::~CHTTPMgr( void )
{
	if( m_hInternetSession )
	{
		::InternetCloseHandle( this->m_hInternetSession );
		this->m_hInternetSession = NULL;
	}
}

BOOL CHTTPMgr::ReadWebPage( LPCTSTR pszURL, tstring &sWebPageContent, UINT nReTryCount /* = DEFAULT_RETRY_COUNT */ )
{
	if( !pszURL ||
		!_tcslen( pszURL ) )
		return FALSE;
	
	sWebPageContent.clear();
	UINT nTryCnt = 0;
	do
	{
		if( this->_ReadWebPage( pszURL, sWebPageContent ) )
			return TRUE;
		
		nTryCnt++;

	} while( nTryCnt < nReTryCount );
	
	return FALSE;
}

BOOL CHTTPMgr::_ReadWebPage( LPCTSTR pszURL, tstring &sWebPageContent )
{
	HTTPFile	httpFile;
	LONG		lStatus;
	DWORD		dwFileSize									= 0;	
	TCHAR		szReadBuffer[ DEFAULT_READ_BUFFER_SIZE ]	= { 0, };
	DWORD		dwBytesRead									= NULL;
	BOOL		bSUCCESS									= FALSE;

	if( !httpFile.ParseURL( pszURL ) )
		return FALSE;
	
	if( !this->GetHttpStatus( httpFile, lStatus ) ||
		HTTP_STATUS_OK != lStatus )
		return FALSE;
	
	/*
	if( !this->GetHttpStatus( httpFile, lStatus )	||
		HTTP_STATUS_OK != lStatus					||
		!this->GetFileSize( httpFile.hFile, dwFileSize ) )
		return FALSE;

	sWebPageContent.reserve( dwFileSize );
	*/

	do
	{
		if( !::InternetReadFile( httpFile.hFile, szReadBuffer, DEFAULT_READ_BUFFER_SIZE, &dwBytesRead )	)
			SET_LAST_ERROR_AND_RETURN_FALSE

#ifdef UNICODE
		WCHAR wszReadBuffer[ DEFAULT_READ_BUFFER_SIZE * 2 + sizeof( WCHAR ) ] = { 0, };
		::MultiByteToWideChar( CP_ACP, 0, ( LPCSTR )szReadBuffer, dwBytesRead, wszReadBuffer, sizeof( wszReadBuffer ) );
		sWebPageContent.append( wszReadBuffer, dwBytesRead );
#else
		sWebPageContent.append( szReadBuffer, dwBytesRead );
#endif

	} while( dwBytesRead );

	tstring::size_type nSize = sWebPageContent.size();
	//return sWebPageContent.size() == dwFileSize ? TRUE : FALSE;

	return nSize ? TRUE : FALSE;
}

BOOL CHTTPMgr::DownLoad( LPCTSTR pszURL, LPCTSTR pszNew, BOOL bCreatePath /* = TRUE */, UINT nReTryCount /* = DEFAULT_RETRY_COUNT */ )
{
	if( !pszURL				||
		!pszNew				||
		!_tcslen( pszURL )	||
		!_tcslen( pszNew ) )
		return FALSE;
	
	if( !FileSystemUtil::IsRealPath( pszNew ) )
		if( !bCreatePath )
			return FALSE;
		else
			if( !FileSystemUtil::MakePath( pszNew, TRUE ) )
				return FALSE;

	UINT nTryCnt = 0;
	do
	{
		if( this->_DownLoad( pszURL, pszNew ) )
			return TRUE;
		
		nTryCnt++;
	} while( nTryCnt < nReTryCount );

	return FALSE;
}

BOOL CHTTPMgr::GetFileSize( const HANDLE hFile, DWORD &dwFileSize )
{
	if( !hFile )
		return FALSE;

	const	UINT	nBufferSize				= 32;
			TCHAR	szBUFFER[ nBufferSize ]	= { 0, };
			DWORD	dwBufLen				= nBufferSize;
	if( !::HttpQueryInfo( hFile, HTTP_QUERY_CONTENT_LENGTH, szBUFFER, &dwBufLen, NULL ) )
		SET_LAST_ERROR_AND_RETURN_FALSE

	dwFileSize = ( DWORD )_ttol( szBUFFER );	
	return TRUE;
}

BOOL CHTTPMgr::_DownLoad( LPCTSTR pszURL, LPCTSTR pszNew )
{
	HTTPFile	httpFile;
	LONG		lStatus;
	DWORD		dwFileSize									= 0;	
	TCHAR		szReadBuffer[ DEFAULT_READ_BUFFER_SIZE ]	= { 0, };
	DWORD		dwBytesRead									= NULL;
	DWORD		dwReadAllSize								= NULL;
	DWORD		dwBytesWritten								= NULL;
	HANDLE		hFile										= INVALID_HANDLE_VALUE;
	BOOL		bSUCCESS									= FALSE;

	if( !httpFile.ParseURL( pszURL ) )
		return FALSE;

	if( !this->GetHttpStatus( httpFile, lStatus ) ||
		HTTP_STATUS_OK != lStatus )
		return FALSE;
	
	/*
	if( !this->GetHttpStatus( httpFile, lStatus )	||
		HTTP_STATUS_OK != lStatus					||
		!this->GetFileSize( httpFile.hFile, dwFileSize ) )
		return FALSE;
	*/

	hFile = ::CreateFile( pszNew, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
	if( INVALID_HANDLE_VALUE == hFile )
		SET_LAST_ERROR_AND_RETURN_FALSE		
	
	do
	{
		if( !::InternetReadFile( httpFile.hFile, szReadBuffer, DEFAULT_READ_BUFFER_SIZE, &dwBytesRead )	||
			!::WriteFile( hFile, szReadBuffer, dwBytesRead, &dwBytesWritten, NULL )						||
			dwBytesRead != dwBytesWritten )
			goto CleanUp;

		dwReadAllSize += dwBytesRead;

	} while( dwBytesRead );

	// bSUCCESS = dwReadAllSize == dwFileSize ? TRUE : FALSE;

CleanUp :

	if( hFile )
	{
		::CloseHandle( hFile );
		hFile = NULL;
	}

	if( !bSUCCESS )
		SET_LAST_ERROR_AND_RETURN_FALSE

	return TRUE;
}

BOOL CHTTPMgr::GetHttpStatus( HTTPFile &httpFile, LONG &lStatus )
{
	if( !this->m_hInternetSession )
		return FALSE;

	if( !( httpFile.hConnection = ::InternetConnect(	this->m_hInternetSession,
														httpFile.strServer.c_str(),
														httpFile.nPort,
														NULL,
														NULL,
														INTERNET_SERVICE_HTTP,
														NULL,
														NULL ) ) )
		SET_LAST_ERROR_AND_RETURN_FALSE

	LPCTSTR ppszAcceptTypes[ 2 ] = { _T( "*/*" ), NULL };
	if( !( httpFile.hFile = ::HttpOpenRequest(	httpFile.hConnection,
												NULL,
												httpFile.strObject.c_str(),
												NULL,
												NULL,
												ppszAcceptTypes,
												INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_KEEP_CONNECTION,
												NULL ) ) )
		SET_LAST_ERROR_AND_RETURN_FALSE

	if( !::HttpSendRequest( httpFile.hFile, NULL, NULL, NULL, NULL ) )
		SET_LAST_ERROR_AND_RETURN_FALSE

	TCHAR szStatusCode[ 32 ];
	DWORD dwStatusSize = 32;
	if( !::HttpQueryInfo( httpFile.hFile, HTTP_QUERY_STATUS_CODE, szStatusCode, &dwStatusSize, NULL ) )
		SET_LAST_ERROR_AND_RETURN_FALSE

	lStatus = _ttol( szStatusCode );
	return TRUE;
}

BOOL CHTTPMgr::GetHttpStatus( LPCTSTR pszURL, LONG &lStatus )
{
	HTTPFile httpFile( pszURL );
	return this->GetHttpStatus( httpFile, lStatus );
}

DWORD CHTTPMgr::GetLastError( void )
{
	return this->m_dwLastError;
}